package com.elbis.util;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URL;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.jboss.logging.Logger;

public class FileCipherDecipher {

	private final String zenginiz = "zenginiz.txt";
	private final String zenginmiyiz = "zenginmiyiz.txt";

	private static final Logger logger = Logger
			.getLogger(FileCipherDecipher.class);

	public FileCipherDecipher() {
	}

	public String getEmailPassword() {

		String pass = null;
		URL url = getClass().getResource(zenginiz);
		if (url == null) {
			logger.error("Cannot read file for the stored decryption key.");
			return null;
		}
		BufferedReader bufferedReader = null;
		try {
			bufferedReader = new BufferedReader(new FileReader(new File(
					url.toURI())));
			String key = bufferedReader.readLine();
			InputStream stream = getClass().getResourceAsStream(zenginmiyiz);
			OutputStream output = new ByteArrayOutputStream();
			decrypt(key, stream, output);
			pass = output.toString();
		} catch (FileNotFoundException e) {
			logger.error("could not find file to read the key", e);
		} catch (URISyntaxException e) {
			logger.error("could not get URI for the key file", e);
		} catch (IOException e) {
			logger.error("error while reading file");
		} catch (Throwable e) {
			logger.error("cipher error", e);
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					logger.error("error while closing the file reader", e);
				}
			}
		}
		return pass;
	}

	public void encrypt(String key, InputStream is, OutputStream os)
			throws Throwable {
		encryptOrDecrypt(key, Cipher.ENCRYPT_MODE, is, os);
	}

	private void decrypt(String key, InputStream is, OutputStream os)
			throws Throwable {
		encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os);
	}

	private void encryptOrDecrypt(String key, int mode, InputStream is,
			OutputStream os) throws Throwable {

		DESKeySpec dks = new DESKeySpec(key.getBytes());
		SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
		SecretKey desKey = skf.generateSecret(dks);
		Cipher cipher = Cipher.getInstance("DES");

		if (mode == Cipher.ENCRYPT_MODE) {
			cipher.init(Cipher.ENCRYPT_MODE, desKey);
			CipherInputStream cis = new CipherInputStream(is, cipher);
			doCopy(cis, os);
		} else if (mode == Cipher.DECRYPT_MODE) {
			cipher.init(Cipher.DECRYPT_MODE, desKey);
			CipherOutputStream cos = new CipherOutputStream(os, cipher);
			doCopy(is, cos);
		}
	}

	private void doCopy(InputStream is, OutputStream os) throws IOException {
		byte[] bytes = new byte[64];
		int numBytes;
		while ((numBytes = is.read(bytes)) != -1) {
			os.write(bytes, 0, numBytes);
		}
		os.flush();
		os.close();
		is.close();
	}

}
